<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>vue2和vue3双向数据绑定原理</title>
</head>
<style type="text/css">

</style>

<body>
    <div>
        <input type="text" id="input" value="默认值">
        <span id="text"></span>
    </div>

    <script type="text/javascript">
        //面试题： vue2和vue3双向数据绑定原理？
        //1.Object.defineProperty基本用法 。Object.defineProperty() 方法会直接在一个对象上定义一个新属性。监听的是这个对象的单个属性
        // var obj = {}
        // Object.defineProperty(obj, "name", {
        //     //get负责拦截
        //     get: function () {
        //         console.log("我来获取值了。。。")
        //     },
        //     //set负责发送
        //     set: function (newVal) {
        //         console.log("我来设置值了。。。", newVal)
        //     }
        // })
        // obj.name = "22"  //设置值，也会被监听到，会执行set方法
        // console.log(32, obj.name)  //获取值时，会执行get方法 。

        //2.vue2双向数据绑定原理
        //    var json={};
        //    Object.defineProperty(json,'name',{
        //        get:function(){
        //            console.log('获取值了');
        //        },
        //        set:function(newVal){
        //            console.log('设置值了',newVal);
        //            document.getElementById('text').innerHTML=newVal;
        //        }

        //    })

        //   document.querySelector('#input').oninput=function(e){
        //       console.log(e.target.id);
        //       json.name=e.target.value;
        //   }

        //2.事件绑定方法
        // var obj = {};
        // Object.defineProperty(obj, 'prop', {
        //     //把设置的新值，返回
        //     get: function () {
        //         return val;
        //     },
        //     //这里不断接受到上面返回的值，写入span中
        //     set: function (newVal) {
        //         val = newVal;
        //         // console.log('设置的值',val);
        //         document.getElementById('text').innerHTML = val; //塞入san中显示
        //     }
        // });
        // //设置值
        // document.addEventListener('keyup', function (e) {
        //     obj.prop = e.target.value;
        // })


        //3.vue3中双向数据绑定-es6 proxy对象监听的整个对象
        var obj = {};
        var obj1 = new Proxy(obj, {
            // target就是第⼀个参数obj, receive就是返回的obj(返回的proxy对象)
            get: function (target, key, receive) {
                // 返回该属性值
                return target[key];
            },
            set: function (target, key, newVal, receive) {
                // 执⾏赋值操作
                console.log('整个对象', target, newVal);
                target[key] = newVal;
                document.getElementById('text').innerHTML = target[key];
            }
        })
        document.addEventListener('keyup', function (e) {
            console.log(obj1);
            obj1['name'] = e.target.value;

        });


//总结:在vue的2.x版本中⽤object.defineProperty来实现双向数据绑定原理，⽽在vue3.0版本中⽤Proxy这个对象来代替object.defineProperty实现数据的双向绑定。但是换汤不换药，这俩种数据双向绑定都是基于数据劫持来实现的。
// 数据劫持：当访问或者设置对象的属性的时候，触发相应的函数，并且返回设置属性的值。
//1.VUE2.0通过Object.defineProperty来劫持对象属性的getter和setter操作，当数据发⽣变化时发出通知
//2.VUE3.0通过Proxy来劫持数据，当数据发⽣变化时发出通知

//3.proxy相较于object.defineProperty的优势
//  3.1.直接监听对象⽽⾮属性
//  3.2.可以监听到数组的变化
//  3.3 Proxy返回⼀个新对象，可以只操作新对象达到⽬的，⽽Object.defineProperty只能遍历对象属性
// 直接修改（需要⽤深拷⻉进⾏修改）

    </script>

</body>

</html>